#include "sq_list.h"

#include <stdio.h>

sq_list *
sq_list_create()
{
	sq_list * l = malloc(sizeof(sq_list));
	memset(l->data, 0, sizeof(elem_t) * SQ_LIST_CAPA);
	l->len = 0;
	return l;
}

void
sq_list_release(sq_list * l)
{
	free(l);
}

int
sq_list_empty(const sq_list * l)
{
	return !!l->len;
}

void
sq_list_clear(sq_list * l)
{
	l->len = 0;
}

int
sq_list_append(sq_list * l, const elem_t * p, size_t len)
{
	for (size_t i = 0; i < len; ++i) {
		if (l->len < SQ_LIST_CAPA) {
			l->data[l->len] = p[i];
			++l->len;
		}
		else {
			return i;
		}
	}

	return len;
}

void
sq_list_display(const sq_list * l)
{
	printf("[%02u] : ", l->len);
	for (size_t i = 0; i < l->len; ++i) {
		printf(" %d,", l->data[i]);
	}
	printf("\n");
}

int
sq_list_get(const sq_list * l, index_t i, elem_t * e)
{
	return (i < l->len) ? (*e = l->data[i], 0) : -1;
}

index_t
sq_list_locate(const sq_list * l, elem_t e)
{
	for (index_t i = 0; i < l->len; ++i) {
		if (l->data[i] == e) {
			return i;
		}
	}

	return -1;
}

int
sq_list_insert(sq_list * l, index_t i, elem_t e)
{
	if (i <= l->len && l->len + 1 <= SQ_LIST_CAPA) {
		for (index_t ti = l->len; ti > i; --ti) {
			l->data[ti] = l->data[ti - 1];
		}
		l->data[i] = e;
		++l->len;
		return 0;
	}
	else {
		return -1;
	}
}

int
sq_list_delete(sq_list * l, index_t i, elem_t * e)
{
	if (i < l->len) {
		*e = l->data[i];
		--l->len;
		for (index_t ti = i; ti < l->len; ++ti) {
			l->data[ti] = l->data[ti + 1];
		}
		return 0;
	}
	else {
		return -1;
	}
}

int
sq_list_delete_range(sq_list * l, elem_t min, elem_t max)
{
	if (min > max) {
		return -1;
	}

	int count = 0;

	elem_t * slot = 0;

	for (index_t i = 0; i < l->len; ++i) {
		if (l->data[i] < min || l->data[i] > max) {
			if (slot) {
				*slot++ = l->data[i];
			}
		}
		else {
			++count;
			if (!slot) {
				slot = l->data + i;
			}
		}
	}

	l->len -= count;

	return count;
}

int
sq_list_delete_range2(sq_list * l, elem_t min, elem_t max)
{
	if (min > max) {
		return -1;
	}

	int i = 0;
	int j = 0;

	for (; i < l->len; ++i) {
		if (l->data[i] < min || l->data[i] > max) {
			if (i != j) {
				l->data[j++] = l->data[i];
			}
			else {
				++j;
			}
		}
	}

	int count = l->len - j;
	l->len = j;
	return count;
}

void
sq_list_rotate(sq_list * l)
{
	elem_t pivot = l->data[0];
	elem_t * p = l->data;
	elem_t * q = l->data + l->len - 1;
	while (p < q) {
		for (; *p < pivot && p < q; ++p) {}
		for (; *q > pivot && q > p; --q) {}
		if (p != q) {
			elem_t temp = *p;
			*p = *q;
			*q = temp;
		}
	}
}

void
sq_list_rotate2(sq_list * l)
{
	elem_t pivot = l->data[0];
	elem_t * slot = l->data;
	elem_t * p = slot + 1;
	elem_t * q = l->data + l->len - 1;

	while (p < q) {
		for (; *q > pivot && q > p; --q) {}
		if (q == p) { break; }
		*slot = *q;
		slot = q;

		for (; *p < pivot && p < q; ++p) {}
		if (p == q) { break; }
		*slot = *p;
		slot = p;
	}

	*p = pivot;
}


